package com.hr.mes.service.impl;

import com.hr.mes.entity.Menu;
import com.hr.mes.entity.Permission;
import com.hr.mes.entity.Role;
import com.hr.mes.entity.User;
import com.hr.mes.service.RoleService;
import com.hr.mes.service.UserService;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 权限相关的缓存服务
 * spring cache是基于aop代理实现的，只有通过代理对象调用PermissionCacheService中的方法，缓存才生效，
 * 所以如果直接在同一个类中调用getAuthorizationInfoFromCache，代理会失效，导致缓存不会生效
 */
@Service
public class PermissionCacheService {

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    /**
     * 如果shiro:permissionList中有employeeNumber，则从缓存中获取用户的角色和权限，没有就查询数据库
     * key = "#employeeNumber"明确指定了缓存的key是参数employeeNumber的值
     * 如果不指定key，1.如果方法没有参数，那么key=SimpleKey.EMPTY；2.如果方法只有一个参数，key默认为该参数的值，和key = "#employeeNumber"或key="#keyname"一样；
     * 3.如果方法有多个参数，key是所有参数值的组合，通过SimpleKey封装
     * @param employeeNumber
     * @return
     */
    @Cacheable(value = "shiro:permissionList", key = "#employeeNumber")
    public SimpleAuthorizationInfo getAuthorizationInfoFromCache(String employeeNumber){
        //设置角色
        User tempUser = userService.getUserByEmployeeNumber(employeeNumber);
        List<Role> roleList = tempUser.getRoleList();
        if(!CollectionUtils.isEmpty(roleList)){
            Set<String> roles = roleList.stream().map(Role::getRoleName).collect(Collectors.toSet());
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
            //设置权限
            HashSet<String> permissions = new HashSet<>();
            for (Role role : roleList){
                Role tempRole = roleService.getRole(role.getRoleId());
                List<Permission> permissionList = tempRole.getPermissionList();
                if(!CollectionUtils.isEmpty(permissionList)){
                    Set<String> tempPermissions= permissionList.stream().map(Permission::getCode).collect(Collectors.toSet());
                    permissions.addAll(tempPermissions);
                }
            }
            info.setStringPermissions(permissions);
            return info;
        }
        return new SimpleAuthorizationInfo();
    }

}
